package com.djf.word.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.djf.word.entity.ImportErrorRow;
import com.djf.word.entity.Order;
import com.djf.word.entity.OrderExcelProgress;
import com.djf.word.service.OrderService;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 订单导入监听器
 * 用于处理Excel文件导入时的逐行解析和进度跟踪
 */
public class OrderImportListener extends AnalysisEventListener<Order> {
    // 批次大小，定义每次批量处理的数据量
    private static final int BATCH_COUNT = 500;
    // 缓存数据列表，存储待处理的订单数据
    private List<Order> cachedDataList = new ArrayList<>(BATCH_COUNT);
    // 订单服务实例，用于执行业务逻辑
    private final OrderService orderService;
    // 当前进度信息对象
    private final OrderExcelProgress progress;
    // 进度标识符
    private final String progressId;
    // 总行数，用于计算进度
    private int totalRows = 0;
    // 进度信息存储容器   //todo实际可换用redis缓存
    private final ConcurrentHashMap<String, OrderExcelProgress> progressMap;
    // 当前行计数器
    private int currentRow = 0;

    private final List<ImportErrorRow> errorRows = new ArrayList<>();

    /**
     * 构造函数
     * @param orderService 订单服务实例
     * @param progress 当前进度信息对象
     * @param progressId 进度标识符
     * @param progressMap 进度信息存储容器
     */
    public OrderImportListener(OrderService orderService, OrderExcelProgress progress, String progressId,  ConcurrentHashMap<String, OrderExcelProgress> progressMap) {
        this.orderService = orderService;
        this.progress = progress;
        this.progressId = progressId;
        this.progressMap = progressMap;
    }

    /**
     * 每解析一行数据时调用
     * @param data 解析得到的订单数据
     * @param context 解析上下文
     */
    @Override
    public void invoke(Order data, AnalysisContext context) {
        currentRow++; // 第一行为数据时是1
        totalRows = context.readRowHolder().getRowIndex() + 1; // 不断刷新总行数
        try {
            //todo 校验 数据 对错误提醒具体化
            cachedDataList.add(data);
            if (cachedDataList.size() >= BATCH_COUNT) {
                orderService.saveBatch(cachedDataList, BATCH_COUNT);
                cachedDataList.clear();
            }
        } catch (Exception e) {
            errorRows.add(new ImportErrorRow(currentRow, e.getMessage()));
        }
        updateProgress();
    }

    /**
     * 所有数据分析完成后调用
     * @param context 解析上下文
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 如果缓存中还有剩余数据，则进行最后一次批量处理
        if (!cachedDataList.isEmpty()) {
            orderService.saveBatch(cachedDataList, BATCH_COUNT);
        }
        // 设置进度为100%
        progress.setProgress(1.0);
        // 预计剩余时间设为0
        progress.setEstimatedSecondsLeft(0);
        // 更新完成消息
        progress.setMessage("导入完成, 总数: " + currentRow);
        // 更新最后更新时间
        progress.setLastUpdateTime(System.currentTimeMillis());
        // 更新进度信息
        progressMap.put(progressId, progress);
    }

    /**
     * 更新处理进度并估计剩余时间
     */
    private void updateProgress() {
        // 计算当前进度百分比
        double percent = totalRows > 0 ? (double) currentRow / totalRows : 0;
        // 获取当前时间
        long now = System.currentTimeMillis();
        // 计算已用时间
        long elapsed = now - progress.getStartTime();
        // 估算总耗时
        long estimatedTotal = (long) (elapsed / (percent > 0 ? percent : 1));
        // 计算预计剩余时间
        long estimatedLeft = estimatedTotal - elapsed;
        // 更新进度百分比
        progress.setProgress(Math.min(percent, 0.99));
        // 更新预计剩余时间（秒）
        progress.setEstimatedSecondsLeft(Math.max(estimatedLeft / 1000, 0));
        // 更新进度描述信息
        progress.setMessage("导入第" + currentRow + "条/共" + totalRows + "条");
        // 更新最后更新时间
        progress.setLastUpdateTime(now);
        // 更新进度信息
        progressMap.put(progressId, progress);
    }

    public List<ImportErrorRow> getErrorRows() {
        return errorRows;
    }

}
